﻿#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<map>
#include<functional>
#include"右值引用和移动语义.h"
#include"task1.h"
#include"MyList.h"
using namespace std;

//void task1()
//{
//	wand wa1 = { "桃心木" , 12.32 , "灵动可变" };
//	wand wa2 = {"龙心弦"};
//	wand wa3 = { "凤凰羽毛" , 11.5, "柔韧" };
//
//	vector<int> v;
//	v = { 4,2,9,5,3 };
//}
////任务2：魔法物品商店（initializer_list进阶）​​
//int GetPrice(const string& st , const map<string,int>& obj)
//{
//	auto ret = obj.find(st);
//	if (ret != obj.end())
//		return ret->second;
//	else
//		return -1;
//}
//void task2()
//{
//	//map<string, int> storeOfMagic = { {"飞天扫帚",1000} , {"隐身衣",5000} , {"魔法石" , 99999} };
//	//map<string, int> storeOfMagic({ {"飞天扫帚",1000} , {"隐身衣",5000} , {"魔法石" , 99999} });
//	map<string, int> storeOfMagic{ {"飞天扫帚",1000} , {"隐身衣",5000} , {"魔法石" , 99999} };
//	//basic search
//	string input;
//	cin >> input;
//	cout << GetPrice(input,storeOfMagic) << endl;
//	//range-for traverse
//	for (auto& au : storeOfMagic)
//	{
//		cout << au.first << "->" << au.second << endl;
//	}
//
//	initializer_list<int> init{ 4,8,9,3,2,5,6 };
//	for (auto& au : init)
//	{
//		cout << au << " " << endl;
//	}
//	cout << &init;
//}
////任务3：幻影移形（右值引用基础）
//void task3()
//{
//	wizard wiz("Harry Potter ","格里莫广场12号");
//	wizard newWiz = wiz.Apparate(move(wiz));
//
//	cout << &newWiz << endl;
//}
//int main()
//{
//	//linhui::test1();
//
//	//task1();
//	//task2();
//	//task3();
//	cout << endl << "hi";
//	return 0;
//}

string&& Apparate(string origination)
{
	string tmp("jif");
	return move(tmp);
}


void test1()
{
	//左值
	/*double* p = new double(2.365);
	float b = 8.9;
	const float c = b;
	*p = 9;
	string st ("huangan");
	st[4] = 'p';

	cout << &c << endl;
	cout << (void*) & st[4] << endl;*/

	//右值
	//cout << &string("jijg");
	//string&& st = Apparate("jifd");

	//&8;
	//int a = 1, b = 3;
	//&(a + b);


	//左右值引用的交叉
	//string left("jifdsf");
	//string&& rref = string("ijon");

	//string& ref = left;

	////string& st = string("ijon");
	//const string& st = string("ijon");
	////string && a= left;
	//string && a = move(left);
}
string Func(string a)
{
	string&& st = string("jfklj");

	return st;
}

//引用参数匹配
void Gosh(int& a)
{
	cout << "左值引用" << endl;
}
void Gosh(const int& a)
{
	cout << "const左值引用" << endl;
}
void Gosh(int&& a)
{
	cout << "右值引用" << endl;
}
void test2()
{
	//引用延长生命周期
	//cout << Func("jif");
	//string tmp = string("fjig");
	string tmp = "jifd";

	const string& st = tmp;
	string&& right = tmp+st;

	//引用参数匹配
	int a = 9;
	const int b = 0;
	Gosh(a);//左值
	Gosh(b);//const左值
	Gosh(9);//右值
	Gosh(move(a)); //被move的左值
	
	int&& c = 8;
	Gosh(c); // 左值引用表达式又是右值引用
	
}


linhui::string AddString(linhui:: string st1,linhui::string st2)
{
	linhui::string tmp("jfidfds");
	//st1 = "fd";
	//st2 = "ihg";
	return tmp;
}
//右值引用和移动语义
void test3()
{
	//linhui::string st("fhudshg");
	/*linhui::string st{ "fhudshg" };
	linhui::string copy(st);

	st = copy;*/

	//linhui::string st1 = "jfid";
	//linhui::string st2 = "jfid";
	cout << endl << endl;
	linhui::string st = AddString("jfid", "jfid");
	//linhui::string st = AddString(st1, st2);

	cout << "-----------" << endl;
	linhui::string st3;
	st3 = AddString("jfid", "jfid");
	//st3 = AddString(st1, st2);
}

template<class T>
void RefFold(T && FomalParameter)
{
	double val = 95.454;
	T tmp = val;
	cout << "&val=" << &val << endl;
	cout << "&tmp=" << &tmp << endl;
	cout << endl;


}


void Child(int& Prefect)
{
	cout << "左值引用" << endl;
}
void Child(int&& Prefect)
{
	cout << "右值引用" << endl;
}
template<class T>
void PerfectForwarding(T&& Prefect)
{
	Child(Prefect);
	Child(forward<T>(Prefect));
	//Child(static_cast<T>(Prefect));
}
//引用折叠和完美转发
void test4()
{
	double val = 9.43;
	const double con = 8.43;
	//RefFold(3.0978); //传右值,T解析为普通类型
	//RefFold(val); //传左值,T解析为普通类型
	//RefFold(con); //传const 右值 , T解析为const右值引用
	

	PerfectForwarding(87);

	
}


//模板参数解析
template<class T , class ... argc>
void decipher(T x , argc ... val)
{

}

//可变模板参数的母题和自己写的
template<class ... argc>
void VariableTem(argc&& ... val)
{
	//cout << sizeof...(argc);
	cout << "可变模板函数" << endl;
}

void VariableTem(int val)
{
	cout << "void VariableTem(int val)" << endl;
}
void VariableTem(int val, double dou)
{
	cout << "void VariableTem(int val, double dou)" << endl;
}
void VariableTem(int val, double dou,const string)
{
	cout << "void VariableTem(int val, double dou , string&& st)" << endl;
}

//第一种包扩展
void ShowList()
{
	return;
}
template<class T , class ...Argc>
void ShowList(T x, Argc&& ... a)
{
	cout << x << " ";
	ShowList(a...);
	return;
}
//第二种包扩展:手动扩展
void ShowList(int x)
{
	cout << x << " ";
}
void ShowList(double x)
{
	cout << x << " ";
}
void ShowList(const char* x)
{
	cout << x << " ";
}
void ShowList(string&& x)
{
	cout << x << " ";
}
template<class ...Argc>
void MyTest(Argc&& ... argc)
{
	
	ShowList(argc ...);
}
//第三种包扩展
template<class T>
 T GetPar( T x)
{
	cout << x << " ";
	return x;
}

template<class ... Argc>
void Arguments(Argc ... argc)
{ }

template<class ... Argc>
void Print(Argc ... argc)
{
	Arguments(GetPar(argc)...);
}

//template<class T>
//T GetVal(T val)
//{
//	return val;
//}
//template<class ... Argc>
//void Argument(Argc ... argc)
//{
//}
template<class T>
T MultiAdd()
{
	cout << "T MultiAdd() called" << endl;
	return 0;
}
template<class T>
T MultiAdd(T x)
{
	cout << " T MultiAdd(T x)called " << endl;
	return x;
}
template<class T , class ... Argc>
T MultiAdd(T x, Argc ... argc)
{
	//ret += Argument(GetVal(argc)...);
	//x += GetList(argc...);
	cout << "Recursive Cave called with x = " << x << endl;
	cout << "Remained Parameter number->" << sizeof...(argc) << endl;
	cout << endl;
	return x + MultiAdd(argc ...);
}

//可变模板参数
void test5()
{
	/*VariableTem(1);
	VariableTem(1, 5.3);
	VariableTem(1, 5.3, "jfid");*/
	
	//MyTest(3, 9.43, "fjidf", string("gfjgk"));
	 //Print(3, 9.43, "fjidf", string("gfjgk"));
	cout << MultiAdd(4, 2, 6, 7, 8);
}

//测试手搓list的有效性,以及emplace_back
void test6()
{
	MyList<linhui::string> ml;
	linhui::string st("fjdinhg");
	/*ml.insert(ml.begin(), st);
	ml.insert(ml.begin(), st);
	ml.insert(ml.begin(), st);
	ml.insert(ml.begin() , st);*/
	/*ml.push_back(st);
	ml.push_back(st);
	ml.push_back(st);
	ml.push_back(st);
	ml.emplace_back(st);*/
	cout << endl;
	ml.emplace_back("hifhdn");
	ml.push_back("jfidh");
	auto it = ml.begin();
	while (it != ml.end())
	{
		cout << *it << " ";
		it++;
	}
	/*cout << endl;
	for (auto au : ml)
	{
		cout << au << " ";
	}*/
}

void Lambda()
{

}
//lambda表达式
double Global = 9;
struct Goods
{
	Goods(string st , double price , int num)
		:_st(st),_price(price),_num(num)
	{ }
	string _st;
	double _price;
	int _num;
};
ostream& operator<<(ostream& out, const Goods& good)
{
	out << good._st << " " << good._num << " " << good._price << endl;
	return out;
}
void test7()
{
	static int  Static = 10;
	double Global = 9;
	//无参lambda
	auto func = []() {cout << "I'm lambda !!!\n"; };
	func();
	//有参lambda
	int x = 5, y = 10 , z = 89;
	auto swap1 = [](int x, int y) {std::swap(x, y); };
	swap1(5, 10);
	cout << x << " " << y;
	//显式捕捉
	auto mat = [x,y]() 
		{
			//Global = 9;
		};
	//隐式捕捉 值捕捉用= . 引用捕捉用&
	//混合捕捉
	auto capture = [& , x , y] ()
		{
			z += 49;
			//x += 1;
			//y += 1;
			Global += 9;
		};
	auto capture1 = [=, &x, &y]()
		{
			//z += 49;
			x += 1;
			y += 1;
			//Global += 9;
		};

	//labmda的应用
	vector<Goods> v = { { "苹果", 2.1, 5 }, { "⾹蕉", 3, 4 }, { "橙⼦", 2.2, 3}, { "菠萝", 1.5, 4 } };
	sort(v.begin(), v.end(), [](Goods left, Goods right) { return left._price > right._price;  });
	for (auto& au : v)
	{
		cout << au;
	}
}

//测试默认的移动构造(移动复制同理)
class DefaultMoveConstructor
{
public:
	DefaultMoveConstructor(int val , linhui::string st)
		:_val(val),_st(st)
	{ }
	/*~DefaultMoveConstructor()
	{

	}*/
	//~DefaultMoveConstructor() = delete;
private:
	int _val;
	linhui::string _st;
};
void test8()
{
	DefaultMoveConstructor obj(4, "897");
	DefaultMoveConstructor copy(obj);
	DefaultMoveConstructor copy1(move(obj)); //添加上拷贝构造/拷贝赋值/析构其中之一,就只会调用string的拷贝构造而不是移动构造了
}

class A 
{ public: 
	A() {} 
	A(int) = delete; 
	static void StaticFunc(int a)
	{
		return  ;
	}
	double OrdinaryFunc(double x, double y)
	{
		return x * y;
	}
};

//包装器
void test9()
{
	int a = 8, y = 0;
	function<int(int, int)> func = [](int a, int y) {return a + y; };
	cout << func(a, y);
	function<void(int)> func1 = &A::StaticFunc;  //包装静态成员变量: &+类域
	function<double(A&&, double, double)> func2 = &A::OrdinaryFunc;
	func2(A(), 4, 3);
}

using placeholders::_1;
using placeholders::_2;
using placeholders::_3;
int TestBind(int x, int y)
{
	return x - y;
}
//bind
void test10()
{
	cout << TestBind(10, 5) <<endl;

	auto func1 = bind(TestBind, _1 , _2);
	auto func2 = bind(TestBind, _2 , _1 );///更换参数顺序(rubbish)
	cout << func1(10, 5) << endl;
	cout << func2(10, 5) << endl;

	auto func3 = bind(TestBind, 1, _1);
	auto func4 = bind(TestBind, _1 , 1);//固定参数值(uesful!!!)
	cout << func3(99) << endl;
	cout << func4(99) << endl;

	string st1 = "aaaa";
	string st2 = "bbbb";
	auto ret = [](string st1, string st2) { return st1 + st2; };
	cout << ret(st1, st2) << endl;

	function<string(string, string)> myFunc = bind(ret, _2, _1);
	cout << myFunc(st1, st2) << endl;

	function<string(string, string)> myFunc1 = bind(ret, "linhui" , _1);//绑定lambda表达式的参数
	cout << myFunc1(st1,st2) << endl;

	//function<double(A&&,double, double)> myFunc2 = &A::OrdinaryFunc;
	function<double(double, double)> myFunc2 = bind(&A::OrdinaryFunc, A(), _1, _2); //绑定类对象,免得调用的时候再传递
	cout << myFunc2(4.3, 9.3);
}

double Money(double origin, int year, double rate)
{
	double ret = origin;
	for (int i = 0; i < year; i++)
	{
		ret += (ret * rate);
	}
	//return ret - origin;
	return ret;
}
//计算复利
void test11()
{
	cout << Money(1000, 3, 0.05);
	function<double(double)> func3_1_5 = bind(Money,_1,45,0.05);
	func3_1_5(2000.2);
}
int main()
{
	//test2();
	//test3();
	//test4();
	//test5();
	//test6();
	//test7();
	//test8();
	//test10();
	test11();

	//return 0;
}